﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using HYRevitCode.FormUtility.ModelessFormControlSuite.ViewLayer;
using YJKRGeometry;

namespace AdjustInstallationHeight
{
	internal class ElementMoveOperator
	{
		public static void MoveElement(UIDocument uiDoc, BeamAndFloorSearcher useSearcher, BaseNoneSwitchForm form, List<FormStructure> formData, ElementNeedMoveAnalyzer useElementAnalyzer)
		{
			List<PrepareMoveStructure> list = GroupCalculation.PrepareMoveData(uiDoc, useElementAnalyzer);
			list = (from data in list
			orderby (data.BeamAndFloorInfo.m_face as PlanarFace).Origin.Z descending
			select data).ToList<PrepareMoveStructure>();
			if (list.Count > 0)
			{
				Transaction transaction = new Transaction(uiDoc.ActiveView.Document, "AdjustInstallationHeight");
				ProgressBarForm progressBarForm = null;
				int num = 0;
				Dictionary<int, XYZ> dictionary = new Dictionary<int, XYZ>();
				uiDoc.Application.Application.FailuresProcessing += ElementMoveOperator.OnFailuresProcessing;
				foreach (PrepareMoveStructure prepareMoveStructure in list)
				{
					foreach (List<Element> list2 in prepareMoveStructure.LstPrepareMoveElement)
					{
						num += list2.Count;
					}
				}
				if (num > ElementMoveOperator.m_nUseFormNumber)
				{
					progressBarForm = new ProgressBarForm(num, ProgressBarStyle.Blocks, true);
				}
				if (progressBarForm != null)
				{
					progressBarForm.Show(CmdAdjustInstallationHeight.m_hWndRevit);
				}
				ElementMoveOperator.m_bIsNeedMove = false;
				Dictionary<ElementId, BeamAndFloorInfo> dictionary2 = new Dictionary<ElementId, BeamAndFloorInfo>();
				foreach (PrepareMoveStructure prepareMoveStructure2 in list)
				{
					List<Element> list3 = new List<Element>();
					using (List<List<Element>>.Enumerator enumerator2 = prepareMoveStructure2.LstPrepareMoveElement.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							list3 = (from k in enumerator2.Current
							orderby (k.Location as LocationCurve).Curve.GetEndPoint(0).Z
							select k).ToList<Element>();
							if (dictionary2.Count > 0)
							{
								if (list3.IsEmpty<Element>())
								{
									continue;
								}
								if (dictionary2.ContainsKey(list3[0].Id))
								{
									if (dictionary2[list3[0].Id].m_name == -2001320 && prepareMoveStructure2.BeamAndFloorInfo.m_name == -2000032)
									{
										continue;
									}
									if (dictionary2[list3[0].Id].m_name != -2000032 || prepareMoveStructure2.BeamAndFloorInfo.m_name != -2001320)
									{
										double z = dictionary2[list3[0].Id].m_face.GetEdgesAsCurveLoops().ElementAt(0).ElementAt(0).GetEndPoint(0).Z;
										double z2 = prepareMoveStructure2.BeamAndFloorInfo.m_face.GetEdgesAsCurveLoops().ElementAt(0).ElementAt(0).GetEndPoint(0).Z;
										if (Geometry.Lessthan_Or_Equal(z, z2))
										{
											continue;
										}
									}
								}
							}
							if (dictionary2.ContainsKey(list3[0].Id))
							{
								dictionary2[list3[0].Id] = prepareMoveStructure2.BeamAndFloorInfo;
							}
							else
							{
								dictionary2.Add(list3[0].Id, prepareMoveStructure2.BeamAndFloorInfo);
							}
							KeyValuePair<double, BuiltInCategory> distance = ElementMoveOperator.GetDistance(list3[0], prepareMoveStructure2.BeamAndFloorInfo.m_face);
							BuiltInCategory value = distance.Value;
							double key = distance.Key;
							double num2 = 0.0;
							if (!ElementMoveOperator.IsNeedMove(formData, value, prepareMoveStructure2.BeamAndFloorInfo, key, out num2))
							{
								if (!progressBarForm.IsDisposed)
								{
									progressBarForm.RefreshProgressBar();
								}
							}
							else
							{
								try
								{
									transaction.Start();
									foreach (Element element in list3)
									{
										XYZ endPoint = (element.Location as LocationCurve).Curve.GetEndPoint(0);
										if (!dictionary.ContainsKey(element.Id.IntegerValue))
										{
											dictionary.Add(element.Id.IntegerValue, endPoint);
										}
										ElementTransformUtils.MoveElement(uiDoc.ActiveView.Document, element.Id, -XYZ.BasisZ * num2);
										ElementMoveOperator.m_bIsNeedMove = true;
										if (progressBarForm != null)
										{
											if (progressBarForm.IsDisposed && progressBarForm.m_stopTag)
											{
												if (transaction.HasStarted())
												{
													transaction.RollBack();
												}
												return;
											}
											progressBarForm.RefreshProgressBar();
											if (progressBarForm.IsDisposed && progressBarForm.m_stopTag)
											{
												if (transaction.HasStarted())
												{
													transaction.RollBack();
												}
												return;
											}
										}
									}
									transaction.Commit();
								}
								catch (Exception)
								{
									if (transaction.HasStarted())
									{
										transaction.RollBack();
									}
								}
							}
						}
					}
				}
				ElementMoveOperator.m_nCount = 0;
				foreach (KeyValuePair<int, XYZ> keyValuePair in dictionary)
				{
					Element elementById = uiDoc.GetElementById(new ElementId(keyValuePair.Key));
					if (elementById != null && !(elementById.Location as LocationCurve).Curve.GetEndPoint(0).IsAlmostEqualTo(keyValuePair.Value))
					{
						ElementMoveOperator.m_nCount++;
					}
				}
				if (progressBarForm != null)
				{
					progressBarForm.Dispose();
				}
				if (ElementMoveOperator.m_bIsNeedMove)
				{
					if (form is OverallForm)
					{
						YJKMessageBox.Show("共完成" + ElementMoveOperator.m_nCount + "处机电设备的调整。");
						return;
					}
					if (form is BranchForm)
					{
						YJKMessageBox.Show(string.Concat(new object[]
						{
							"共完成",
							ElementMoveOperator.m_nCount,
							"处",
							(form as BranchForm).Text.Substring(0, 2),
							"设备的调整。"
						}));
						return;
					}
				}
				else
				{
					YJKMessageBox.Show("所选构件均满足设定的间距值，无需做调整处理。");
				}
			}
		}

		private static void OnFailuresProcessing(object sender, FailuresProcessingEventArgs e)
		{
			FailuresAccessor failuresAccessor = e.GetFailuresAccessor();
			string transactionName = failuresAccessor.GetTransactionName();
			if (failuresAccessor.GetFailureMessages().Count == 0)
			{
				e.SetProcessingResult((FailureProcessingResult)0);
				return;
			}
			if (transactionName.Equals("AdjustInstallationHeight"))
			{
				e.SetProcessingResult((FailureProcessingResult)1);
				return;
			}
		}

		private static bool IsNeedMove(List<FormStructure> formData, BuiltInCategory builtInCategory, BeamAndFloorInfo beamAndFloorInfo, double dDistance, out double dMoveDistance)
		{
			foreach (FormStructure formStructure in formData)
			{
				if (formStructure.ElementType == builtInCategory)
				{
					if (beamAndFloorInfo.m_name == -2001320 && !Geometry.IsEqual(dDistance, AssistFunc.mmToFeet(formStructure.DDistanceToBeam)))
					{
						dMoveDistance = AssistFunc.mmToFeet(formStructure.DDistanceToBeam) - dDistance;
						return true;
					}
					if (beamAndFloorInfo.m_name == -2000032 && !Geometry.IsEqual(dDistance, AssistFunc.mmToFeet(formStructure.DDistanceToFloor)))
					{
						dMoveDistance = AssistFunc.mmToFeet(formStructure.DDistanceToFloor) - dDistance;
						return true;
					}
				}
			}
			dMoveDistance = 0.0;
			return false;
		}

		private static KeyValuePair<double, BuiltInCategory> GetDistance(Element element, Face face)
		{
			double num = 0.0;
			double num2 = 0.0;
            BuiltInCategory value = BuiltInCategory.OST_DuctCurves;
			ElementMoveOperator.CalculateDistanceOfCurveToFace((element.Location as LocationCurve).Curve, face as PlanarFace, out num);
			int integerValue = element.Category.Id.IntegerValue;
			if (integerValue != -2008130)
			{
				if (integerValue != -2008044)
				{
					if (integerValue == -2008000)
					{
						if (ElementMoveOperator.GetElementHeight(element as Duct, out num2))
						{
							num -= num2 / 2.0;
						}
                        value = BuiltInCategory.OST_DuctCurves;
					}
				}
				else
				{
					if (ElementMoveOperator.GetElementHeight(element as Pipe, out num2))
					{
						num -= num2 / 2.0;
					}
                    value = BuiltInCategory.OST_PipeCurves;
				}
			}
			else
			{
				if (ElementMoveOperator.GetElementHeight(element as CableTray, out num2))
				{
					num -= num2 / 2.0;
				}
                value = BuiltInCategory.OST_CableTray;
			}
			return new KeyValuePair<double, BuiltInCategory>(num, value);
		}

		public static bool CalculateDistanceOfCurveToFace(Curve inputCurve, PlanarFace inputPlanarFace, out double dDistanceValue)
		{
			dDistanceValue = 0.0;
			Curve curve = null;
			if (!GroupCalculation.CurveProjectToPlanarFace(inputCurve, inputPlanarFace, out curve))
			{
				return false;
			}
			XYZ xyz = curve.Evaluate(0.5, true);
			IntersectionResult intersectionResult = inputCurve.Project(xyz);
			if (intersectionResult == null || intersectionResult.XYZPoint == null)
			{
				return false;
			}
			dDistanceValue = xyz.DistanceTo(intersectionResult.XYZPoint);
			if (Geometry.LessThan(xyz.Z, intersectionResult.XYZPoint.Z))
			{
				dDistanceValue = -dDistanceValue;
			}
			XYZ xyz2 = intersectionResult.XYZPoint.Add(-xyz).Normalize();
			return xyz2.IsAlmostEqualTo(inputPlanarFace.FaceNormal()) || xyz2.IsAlmostEqualTo(-inputPlanarFace.FaceNormal());
		}

		private static bool GetElementHeight(Duct duct, out double dHeight)
		{
			Parameter parameter = duct.GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);
			if (parameter != null)
			{
				dHeight = parameter.AsDouble();
				return true;
			}
			dHeight = 0.0;
			return false;
		}

		private static bool GetElementHeight(Pipe pipe, out double dHeight)
		{
			Parameter parameter = pipe.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
			if (parameter != null)
			{
				dHeight = parameter.AsDouble();
				return true;
			}
			dHeight = 0.0;
			return false;
		}

		private static bool GetElementHeight(CableTray cable, out double dHeight)
		{
			Parameter parameter = cable.GetParameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM);
			if (parameter != null)
			{
				dHeight = parameter.AsDouble();
				return true;
			}
			dHeight = 0.0;
			return false;
		}

		private static int m_nUseFormNumber = 0;

		private static List<ElementId> m_lstElementId = new List<ElementId>();

		private static int m_nCount = 0;

		private static bool m_bIsNeedMove = false;
	}
}
